package com.onlyxiahui.extend.query.hibernate;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.Id;

import com.onlyxiahui.extend.query.hibernate.syntax.data.QueryHandleData;
import com.onlyxiahui.extend.query.hibernate.syntax.data.QueryHandleUtil;
import com.onlyxiahui.extend.query.hibernate.syntax.util.UpdateHqlUtil;
import com.onlyxiahui.extend.query.hibernate.util.DbReflectUtil;
import com.onlyxiahui.extend.query.hibernate.util.EntityUtil;
import com.onlyxiahui.extend.query.hibernate.util.QueryUtil;
import com.onlyxiahui.extend.query.page.QueryPage;

/**
 * 
 * Date 2019-01-07 21:43:56<br>
 * Description
 * 
 * @author XiaHui<br>
 * @since 1.0.0
 */
public abstract class AbstractEntityDAO<T> extends AbstractDAO {

	@SuppressWarnings("unchecked")
	public Class<T> getEntityClass() {
		Type type = this.getClass().getGenericSuperclass();
		ParameterizedType parameterizedType = (ParameterizedType) type;
		Type[] types = parameterizedType.getActualTypeArguments();
		Class<T> entityClass = null;
		if (types.length > 0) {
			Type valueType = types[0];
			if (valueType instanceof Class<?>) {
				entityClass = (Class<T>) valueType;
			}
		}
		return entityClass;
	}

	public String getEntityName() {
		String entityName = "";
		Class<T> entityClass = (Class<T>) getEntityClass();
		if (null != entityClass) {
			entityName = entityClass.getName();
		}
		return entityName;
	}

	public String getTableName() {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return EntityUtil.getTableName(entityClass);
	}

	public T getById(Serializable id) {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return this.get(entityClass, id);
	}

	public T get(Object query) {
		if (null == query) {
			return null;
		} else {
			Class<T> entityClass = (Class<T>) getEntityClass();
			return this.get(entityClass, query);
		}
	}

	public T get(QueryWrapper queryWrapper) {
		if (null == queryWrapper ||
				null == queryWrapper.getParameterMap() ||
				queryWrapper.getParameterMap().isEmpty()) {
			return null;
		} else {
			Class<T> entityClass = (Class<T>) getEntityClass();
			return this.get(entityClass, queryWrapper);
		}
	}

	public int updateSelective(QueryWrapper qw) {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return updateSelective(entityClass, qw);
	}

	public int updateSelective(Map<String, Object> map) {
		QueryWrapper qw = QueryUtil.getQueryWrapper(map);
		return updateSelective(qw);
	}

	public int updateSelective(Serializable id, QueryWrapper qw) {
		int count = 0;
		Class<T> entityClass = (Class<T>) getEntityClass();
		if (null != entityClass) {
			String entityName = entityClass.getName();
			Field field = DbReflectUtil.getField(entityClass, Object.class, Id.class);
			if (null != field) {
//				Column c = field.getAnnotation(Column.class);
//				String idName = (null == c || c.name() == null) ? field.getName() : c.name();
				String idName = field.getName();
				qw.addParameter(idName, id);

				String hql = UpdateHqlUtil.getUpdateHql(entityName, idName, qw);
				count = this.executeHql(hql, qw);
			} else {
				throw new RuntimeException("找不到" + entityName + "实体的主键");
			}
		} else {
			throw new RuntimeException("实体类不能为空");
		}
		return count;
	}

	public int updateSelective(QueryWrapper qw, List<String> keyNames) {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return super.updateSelective(entityClass, qw, keyNames);
	}

	public int updateSelective(Object data, List<String> keyNames) {
		QueryWrapper qw = QueryUtil.getQueryWrapper(data);
		return updateSelective(qw, keyNames);
	}

	public int updateSelective(QueryWrapper qw, String... keyNames) {
		List<String> keyNameList = new ArrayList<>();
		if (null != keyNames) {
			for (String key : keyNames) {
				keyNameList.add(key);
			}
		}
		return updateSelective(qw, keyNameList);
	}

	public int updateSelective(Object data, String... keyNames) {
		QueryWrapper qw = QueryUtil.getQueryWrapper(data);
		return updateSelective(qw, keyNames);
	}

	public int deleteById(Serializable id) {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return this.deleteById(entityClass, id);
	}

	/**
	 * 
	 * 条件删除 <br>
	 * Date 2020-12-09 19:18:41<br>
	 * 
	 * @param qw
	 * @return
	 * @since 1.0.0
	 */
	public int deleteByCondition(QueryWrapper qw) {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return deleteByCondition(entityClass, qw);
	}

	/**
	 * 
	 * 条件删除 <br>
	 * Date 2020-12-09 19:18:54<br>
	 * 
	 * @param data
	 * @return
	 * @since 1.0.0
	 */
	public int deleteByCondition(Object data) {
		QueryWrapper qw = QueryUtil.getQueryWrapper(data);
		return deleteByCondition(qw);
	}

	public List<T> list(Object query) {
		QueryHandleData queryHandleData = QueryHandleUtil.get(query);
		QueryWrapper queryWrapper = QueryUtil.getQueryWrapperType(query, queryHandleData.getOptions());
		return this.list(queryWrapper, queryHandleData);
	}

	public List<T> list(QueryWrapper queryWrapper) {
		return list(queryWrapper, (QueryHandleData) null);
	}

	public List<T> list(Object query, QueryPage page) {
		QueryHandleData queryHandleData = QueryHandleUtil.get(query);
		QueryWrapper queryWrapper = QueryUtil.getQueryWrapperType(query, queryHandleData.getOptions());
		queryWrapper.setPage(page);
		return list(queryWrapper, queryHandleData);
	}

	public List<T> list(QueryWrapper queryWrapper, QueryHandleData queryHandleData) {
		Class<T> entityClass = (Class<T>) getEntityClass();
		return this.list(entityClass, queryWrapper, queryHandleData);
	}
}
